package me.ereach.reflections;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyTest {
    @Test
    public void test08() {
        var p = MyTest.class.getClassLoader().getResource("db.properties").getPath();
        System.out.println(p);
    }

    @Test
    public void test07() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        // 获取Point3D的字节码
        Class point3DClass = Class.forName("me.ereach.reflections.Point3D");
        // 获取Point3D的构造方法
        Constructor constructor = point3DClass.getConstructor(float.class, float.class, float.class);
        // 创建一个Point3D的实例
        Object p3d = constructor.newInstance(2, 3, 5);
        // 输出Point3D实例
        System.out.println(p3d);

        // 获取私有属性 x 并设置可访问型
        Field x = point3DClass.getDeclaredField("x");
        x.setAccessible(true);
        x.set(p3d, 7);

        // 获取私有属性 y 并设置可访问型
        Field y = point3DClass.getDeclaredField("y");
        y.setAccessible(true);
        y.set(p3d, 11);

        // 获取私有属性 z 并设置可访问型
        Field z = point3DClass.getDeclaredField("z");
        z.setAccessible(true);
        z.set(p3d, 13);

        System.out.println(p3d);

        Object p3d2 = constructor.newInstance(2, 3, 5);

        // 获取私有方法
        Method getDistance = point3DClass.getDeclaredMethod("getDistance", Point3D.class);
        getDistance.setAccessible(true);
        Object distance = getDistance.invoke(p3d, p3d2);
        System.out.println(distance);
    }

    // 下面的例子可以拿到类的公有属性
    @Test
    public void test06() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 获取类的字节码对象
        Class point3DClass = Class.forName("me.ereach.reflections.Point3D");
        // 获取构造函数
        Constructor constructor = point3DClass.getConstructor(float.class, float.class, float.class);
        // 通过构造函数创建点实例
        Object instance = constructor.newInstance(2, 3, 5);

        // 获取类的公有属性
        Field[] fields = point3DClass.getFields();

        // 输出类的公有属性, 没有公有属性，没有输出
        for (Field field : fields)
            System.out.println(field);
    }

    @Test
    public void test05() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 获取类的字节码对象
        Class point3DClass = Class.forName("me.ereach.reflections.Point3D");

        // 获取类的构造方法
        Constructor constructor = point3DClass.getConstructor(float.class, float.class, float.class);

        // 通过构造方法创建类的实例对象
        Object p1 = constructor.newInstance(2, 3, 5);
        Object p2 = constructor.newInstance(7, 11, 13);

        // 获取类的私有方法并设置可访问属性
        Method getDistance = point3DClass.getDeclaredMethod("getDistance", point3DClass);
        getDistance.setAccessible(true);

        // 调用该私有方法计算两点的距离
        System.out.println(getDistance.invoke(p1, p2));
    }

    /**
     * 本例演示获取构造方法
     */
    @Test
    public void test04() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class point3DClass = Class.forName("me.ereach.reflections.Point3D");
        Constructor[] constructors = point3DClass.getConstructors();

        // 获取全部构造方法
        for (Constructor x : constructors)
            System.out.println(x);

        // 获取当个构造方法
        Constructor constructor = point3DClass.getDeclaredConstructor(float.class, float.class, float.class);

        // 通过构造方法创建对象
        Object instance = constructor.newInstance(2, 3, 5);
        System.out.println(instance);
    }

    @Test
    public void test03() throws ClassNotFoundException {
        Class pointClass = Class.forName("me.ereach.reflections.Point");

        System.out.println(pointClass);
    }

    @Test
    public void test02() {
        Class pointClass = Point.class;

        System.out.println(pointClass);
    }

    @Test
    public void test01() {
        Point p = new Point(2, 3);

        // 获取类的字节码对象
        Class pointClass = p.getClass();

        System.out.println(pointClass);
    }
}
